package cs422.project2.sketch;

import java.util.ArrayList;

import omicronAPI.OmicronTouchListener;
import processing.core.PApplet;
import processing.core.PFont;
import cs422.project2.sketch.data.Variable;
import cs422.project2.sketch.gui.ColorCode;
import cs422.project2.testing.FloatTable;
import cs422.project2.testing.Integrator;

public class TimeLineSketch extends Sketch implements OmicronTouchListener{
	
	FloatTable data;
	float dataMin, dataMax;

	float labelX, labelY;

	int rowCount;
	int columnCount;
	
	int yearMin, yearMax;
	int[] years;

	int yearInterval = 10;
	int volumeInterval = 10;
	int volumeIntervalMinor = 5;

	float[] tabLeft, tabRight;
	float tabTop, tabBottom;
	float tabPad = 10;

	ArrayList<Integrator> interpolators[];

	PFont plotFont; 

	private DrawLine datLine;
	
	public TimeLineSketch(Variable d) {
		super(d);
		datLine = new DrawLine(false, 1950);
	
	/**
	 * TODO remove
	 * This is for testing the new graph
	 */
	
		  data = new FloatTable(this.parent, "../milk-tea-coffee.tsv");
		  rowCount = data.getRowCount();
		  columnCount = data.getColumnCount();
		  
		  
		 
		  years = PApplet.parseInt(data.getRowNames());
		  yearMin = years[0];
		  yearMax = years[years.length - 1];
		  
		  dataMin = 0;
		  dataMax = 100;
				  //PApplet.ceil(data.getRowMax() / volumeInterval) * volumeInterval;

		  // intializing the interpolators
		  interpolators = new ArrayList[rowCount];
		  for( int col = 0; col < columnCount; col++){
			  interpolators[col] = new ArrayList<Integrator>();
		  }
		  
		  for (int row = 0; row < rowCount; row++) {
			  float initialValue = 0;
			  for( int col = 0; col < columnCount; col++){
				initialValue += data.getFloat(row, col);
				float sum = data.getRowSum(row);
				float percent = parent.floor(((initialValue * 100)/sum));
				if(col == columnCount - 1){
					percent = 100;
				}
			    Integrator ig = new Integrator(0);
			    ig.target(percent);
			    ig.attraction = (float) (0.1 ); 
				interpolators[col].add(ig);
			  }
		  }

		 // plotX1 = 120; 
		 // plotX2 = parent.width - 80;
		  labelX = plotX1 - 50;
		//  plotY1 = 60;
		//  plotY2 = parent.height - 70;
		  labelY = plotY2 + 50;
		  
		  plotFont = parent.createFont("SansSerif", 20);
		  parent.textFont(plotFont);
	
	}

	@Override
	public void display() {
		super.display();
		  parent.background(224);
		  
		  // Show the plot area as a white box  
		  parent.fill(255);
		  parent.rectMode(PApplet.CORNERS);
		  parent.noStroke();
		  parent.rect(plotX1, plotY1, plotX2, plotY2);

		  //parent.drawTitleTabs();
		  drawAxisLabels();

		  for (int col = 0; col < columnCount; col++) {
			  for (int row = 0; row < rowCount; row++) {
			    interpolators[col].get(row).update();
			  }
		  }

		   drawYearLabels();
		   drawVolumeLabels();
		   
		  
		   
		   parent.noStroke();
		//   parent.fill(0x5679C1);
		   for(int col = 0; col < columnCount; col++)
			   drawDataArea(col);
		   
		    //drawBars(columnCount - 1);	  
		   this.datLine.showData();
	}

	public void drawAxisLabels() {
		  parent.fill(0);
		  parent.textSize(13);
		  parent.textLeading(15);
		  
		  parent.textAlign(PApplet.CENTER, PApplet.CENTER);
		  parent.text("Gallons\nconsumed\nper capita", labelX, (plotY1+plotY2)/2);
		  parent.textAlign(PApplet.CENTER);
		  parent.text("Year", (plotX1+plotX2)/2, labelY);
		}


	void drawYearLabels() {
		parent.fill(0);
		parent.textSize(10);
		parent.textAlign(PApplet.CENTER);

		// Use thin, gray lines to draw the grid
		parent.stroke(224);
		parent.strokeWeight(1);

		for (int row = 0; row < rowCount; row++) {
			if (years[row] % yearInterval == 0) {
				
				float x = PApplet.map(years[row], yearMin, yearMax, plotX1, plotX2);
				parent.text(years[row], x, plotY2 + parent.textAscent() + 10);
				parent.line(x, plotY1, x, plotY2);
			}
		}
	}


	void drawVolumeLabels() {
		parent.fill(0);
		parent.textSize(10);
		parent.textAlign(parent.RIGHT);

		parent.stroke(128);
		parent.strokeWeight(1);

		for (float v = dataMin; v <= dataMax; v += volumeIntervalMinor) {
			if (v % volumeIntervalMinor == 0) {     // If a tick mark
				float y = parent.map(v, dataMin, dataMax, plotY2, plotY1);  
				if (v % volumeInterval == 0) {        // If a major tick mark
					float textOffset = parent.textAscent()/2;  // Center vertically
					if (v == dataMin) {
						textOffset = 0;                   // Align by the bottom
					} else if (v == dataMax) {
						textOffset = parent.textAscent();        // Align by the top
					}
					parent.text(parent.floor(v), plotX1 - 10, y + textOffset);
					parent.line(plotX1 - 4, y, plotX1, y);     // Draw major tick
				} else {
					//line(plotX1 - 2, y, plotX1, y);   // Draw minor tick
				}
			}
		}
	}

	public void drawDataArea(int col) {
		parent.pushStyle();
		ColorCode color = new ColorCode();
		parent.noStroke();
		parent.fill(color.getColor(col).getRGB());
		
		parent.beginShape();
		
		for (int row = 0; row < rowCount; row++) {
			if (data.isValid(row, col)) {
				
				float value = interpolators[col].get(row).getValue();
				
				float x = parent.map(years[row], yearMin, yearMax, plotX1, plotX2);
				float y = parent.map(value, dataMin, dataMax, plotY2, plotY1);
				parent.vertex(x, y);
			}
		}
		
		if(col > 0){
			for (int row = rowCount - 1; row >= 0; row--) {
				if (data.isValid(row, col - 1)) {
					float value = interpolators[col - 1].get(row).getValue();
					float x = parent.map(years[row], yearMin, yearMax, plotX1, plotX2);
					float y = parent.map(value, dataMin, dataMax, plotY2, plotY1);
					parent.vertex(x, y);
				}
			}
		}
		else{
			parent.vertex(plotX2, plotY2);
			parent.vertex(plotX1, plotY2);
		}
		
		parent.endShape(parent.CLOSE);
		parent.popStyle();
	}

	public void drawBars(int col){
		float barWidth = 0;
		for (int row = 0; row < rowCount; row++) {
			if (data.isValid(row, col)) {
				float value = interpolators[col].get(row).getValue();
				float x = parent.map(years[row], yearMin, yearMax, plotX1, plotX2);
				float y = parent.map(value, dataMin, dataMax, plotY2, plotY1);
				float x2 = parent.map(years[row]+1, yearMin, yearMax, plotX1, plotX2);
				barWidth = x2 - x; 
				parent.pushStyle();
				parent.stroke(200);
				parent.noFill();
				//parent.line(x, plotY2, x, y);
				parent.rect(x, y, x+barWidth, plotY2);
				parent.popStyle();
			}
		}
		
	}
	public void touchDown(int ID, float xPos, float yPos, float xWidth, float yWidth){
		  parent.noFill();
		  parent.stroke(255,0,0);
		  parent.ellipse( xPos, yPos, xWidth * 2, yWidth * 2 );
		  
		  if(xPos > plotX1 && xPos < plotX2){
			  int year = parent.floor(parent.map(xPos, plotX1, plotX2, yearMin, yearMax));
			  this.datLine.setYear(year);
		  }
	}
	
	@Override
	public void touchMove(int arg0, float arg1, float arg2, float arg3,
			float arg4) {
		// TODO Auto-generated method stub
		
	}
	
	@Override
	public void touchUp(int arg0, float arg1, float arg2, float arg3, float arg4) {
		// TODO Auto-generated method stub
		
	}
	
	class DrawLine{
		boolean isVisible = false;
		int year;
		
		public DrawLine(boolean isVisible, int year) {
			this.isVisible = isVisible;
			this.year = year;
		}
		
		public boolean isVisible() {
			return isVisible;
		}

		public void setVisible(boolean isVisible) {
			this.isVisible = isVisible;
		}

		public int getYear() {
			return year;
		}

		public void setYear(int year) {
			this.year = year;
		}

		public void showData(){
			if(!isVisible && year == 0) return;
			
			parent.pushStyle();
			// draw the line from ploty2 to y
			parent.stroke(255);
			parent.strokeWeight(1);
			
			// get the y co ordinate
			int rowIndex = data.getRowIndex(parent.str(year));
			float yDat = 0;
			float x = parent.map(year, yearMin, yearMax, plotX1, plotX2);
			float y;
			for(int col = 0; col < columnCount; col++){
				yDat += data.getFloat(rowIndex, col);
				y = parent.map(yDat, dataMin, dataMax, plotY2, plotY1);
				parent.pushStyle();
				parent.strokeWeight(5);
		        parent.point(x, y);
		        parent.popStyle();
			}
			y = parent.map(yDat, dataMin, dataMax, plotY2, plotY1);
			
			parent.pushStyle();
			parent.strokeWeight(5);
	        parent.point(x, y);
	        parent.popStyle();
			
			parent.line(x, plotY2, x, y);
			
			// draw points at the intersection
			// display text at the center
			parent.popStyle();
		}
	}

}
